//------------------------------------------------------------------------------
// Utils.h
//------------------------------------------------------------------------------
// File provided for Microsoft Shared Source.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
// PARTICULAR PURPOSE.
//------------------------------------------------------------------------------
//
// Utility/helper functions
//
//------------------------------------------------------------------------------

#pragma once

#include <msi.h>

HRESULT LoadAndLockResource(__in HINSTANCE hinst, UINT uiResID, const WCHAR *pszType, __out void **ppvRes, __out DWORD *pcb);
HRESULT LoadPopupMenu(__in HINSTANCE hinst, UINT uiResID, __out HMENU *phmnu);
void SetThreadName(DWORD dwThreadID, const char *pszThreadName);
STDAPI PathGetNarrowPath(__in PCWSTR pszPath, __deref_out PWSTR *ppszNarrowPath);

template<typename K, typename V, class KTraits, class VTraits>
HRESULT CloneMap(const CAtlMap<K, V, KTraits, VTraits> &mapSrc, __inout CAtlMap<K, V, KTraits, VTraits> &mapDst)
{
    HRESULT hr = S_OK;
    try
    {
        POSITION pos = mapSrc.GetStartPosition();
        while (pos)
        {
            const CAtlMap<K, V, KTraits, VTraits>::CPair *pPair = mapSrc.GetNext(pos);
            mapDst.SetAt(pPair->m_key, pPair->m_value);
        }
    }
    catch (CAtlException &e)
    {
        hr = e.m_hr;
    }
    return hr;
}

// This macro declares the c_sz and c_cch variables if you
// have some string constants you need to use a bunch of times.
// WARNING:
// In your implementation if you are trying to search your source
// for the declaration "c_szFoo" you will need to just search for "Foo".
#define DECLARE_SZ(name, sz)    \
    const WCHAR * const c_sz##name = L##sz;   \
    const int c_cch##name = ARRAYSIZE(L##sz) - 1;


template <class Tobj, class Tflag>
inline Tobj SetFlag(Tobj &obj, Tflag f) { return ((obj) |= (f)); }

template <class Tobj, class Tflag>
inline Tobj ToggleFlag(Tobj &obj, Tflag f) { return ((obj) ^= (f)); }

template <class Tobj, class Tflag>
inline Tobj ClearFlag(Tobj &obj, Tflag f) { return ((obj) &= ~(f)); }

template <class Tobj, class Tflag>
inline BOOL IsFlagSet(Tobj obj, Tflag f) { return (((obj) & (f)) == (f)); }

template <class Tobj, class Tflag>
inline BOOL IsFlagClear(Tobj obj, Tflag f) { return (((obj) & (f)) != (f)); }

struct sdiv_t
{
    size_t quot;
    size_t rem;
};

inline sdiv_t sdiv(size_t numerator, size_t denominator)
{
    sdiv_t divRes;
    divRes.quot = numerator / denominator;
    divRes.rem = numerator % denominator;
    return divRes;
}

HRESULT GetMsiProperty(MSIHANDLE hmsi, PCWSTR pszPropName, __deref_out PWSTR *ppszProp);
